#![allow(unused_imports, non_snake_case, non_camel_case_types, unused_variables)]
use super::windows::*;
use super::*;

#[repr(C)]
#[allow(non_camel_case_types)]
pub struct TextSource<'a> {
	vtbl: IDWriteTextAnalysisSourceVtbl,
	text: &'a mut [u16],
	locale: &'a mut [u16],
	rtl: bool,
}
impl<'a> TextSource<'a> {
	pub fn new(text: &'a mut [u16], locale: &'a mut [u16], rtl: bool) -> Self {
		unsafe extern "system" fn QueryInterface(This: *mut IUnknown, riid: REFIID, ppvObject: *mut *mut c_void) -> HRESULT {
			*ppvObject = ptr::null_mut();
			S_FALSE
		}
		unsafe extern "system" fn AddRef(This: *mut IUnknown) -> ULONG {
			1
		}
		unsafe extern "system" fn Release(This: *mut IUnknown) -> ULONG {
			1
		}
		unsafe extern "system" fn GetTextAtPosition(This: *mut IDWriteTextAnalysisSource, textPosition: UINT32, textString: *mut *const WCHAR, textLength: *mut UINT32) -> HRESULT {
			let this = This as *mut c_void as *mut *mut TextSource<'static>;
			let this = &mut **this;
			this.GetTextAtPosition(textPosition, textString, textLength);
			S_OK
		}
		unsafe extern "system" fn GetTextBeforePosition(This: *mut IDWriteTextAnalysisSource, textPosition: UINT32, textString: *mut *const WCHAR, textLength: *mut UINT32) -> HRESULT {
			let this = This as *mut c_void as *mut *mut TextSource<'static>;
			let this = &mut **this;
			this.GetTextBeforePosition(textPosition, textString, textLength);
			S_OK
		}
		unsafe extern "system" fn GetParagraphReadingDirection(This: *mut IDWriteTextAnalysisSource) -> DWRITE_READING_DIRECTION {
			let this = This as *mut c_void as *mut *mut TextSource<'static>;
			let this = &mut **this;
			this.GetParagraphReadingDirection()
		}
		unsafe extern "system" fn GetLocaleName(This: *mut IDWriteTextAnalysisSource, textPosition: UINT32, textLength: *mut UINT32, localeName: *mut *const WCHAR) -> HRESULT {
			let this = This as *mut c_void as *mut *mut TextSource<'static>;
			let this = &mut **this;
			this.GetLocaleName(textPosition, textLength, localeName);
			S_OK
		}
		unsafe extern "system" fn GetNumberSubstitution(This: *mut IDWriteTextAnalysisSource, textPosition: UINT32, textLength: *mut UINT32, numberSubstitution: *mut *mut IDWriteNumberSubstitution) -> HRESULT {
			let this = This as *mut c_void as *mut *mut TextSource<'static>;
			let this = &mut **this;
			this.GetNumberSubstitution(textPosition, textLength, numberSubstitution);
			S_OK
		}
		Self {
			vtbl: IDWriteTextAnalysisSourceVtbl {
				parent: IUnknownVtbl {
					QueryInterface, //
					AddRef,
					Release,
				}, //
				GetTextAtPosition,
				GetTextBeforePosition,
				GetParagraphReadingDirection,
				GetLocaleName,
				GetNumberSubstitution,
			},
			text,
			locale,
			rtl,
		}
	}
	unsafe fn GetTextAtPosition(&mut self, textPosition: UINT32, textString: *mut *const WCHAR, textLength: *mut UINT32) {
		let text = self.text.get_mut(textPosition as usize..).unwrap_or_default();
		*textLength = text.len() as _;
		*textString = text.as_mut_ptr();
	}
	unsafe fn GetTextBeforePosition(&mut self, textPosition: UINT32, textString: *mut *const WCHAR, textLength: *mut UINT32) {
		let text = self.text.get_mut(..textPosition as usize).unwrap_or_default();
		*textLength = text.len() as _;
		*textString = text.as_mut_ptr();
	}
	unsafe fn GetParagraphReadingDirection(&mut self) -> DWRITE_READING_DIRECTION {
		if self.rtl {
			DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
		} else {
			DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
		}
	}
	unsafe fn GetLocaleName(&mut self, textPosition: UINT32, textLength: *mut UINT32, localeName: *mut *const WCHAR) {
		*textLength = (self.text.len() as UINT32).saturating_sub(textPosition);
		*localeName = self.locale.as_mut_ptr();
	}
	unsafe fn GetNumberSubstitution(&mut self, textPosition: UINT32, textLength: *mut UINT32, numberSubstitution: *mut *mut IDWriteNumberSubstitution) {
		*textLength = (self.text.len() as UINT32).saturating_sub(textPosition);
		*numberSubstitution = ptr::null_mut();
	}
}
